package util;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.RollbackException;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;

public class DaoGenerico {

	private static EntityManagerFactory factory = Persistence.createEntityManagerFactory("AutoMecPU");
	private static EntityManager em = factory.createEntityManager();

	public static void salvar(Object obj){
		try{
			if (!em.getTransaction().isActive())
				em.getTransaction().begin();

			//em.persist(obj);
			em.merge(obj);

			if (em.getTransaction().isActive())
				em.getTransaction().commit();

		} catch (Exception e) {
			if (em.getTransaction().isActive())
				em.getTransaction().rollback();
			throw new RuntimeException(e);
		}
	}

	@SuppressWarnings("unchecked")
	public static List<Object> executaQuery(String query) {

		List<Object> result = null;

		try {

			if (!em.getTransaction().isActive())
				em.getTransaction().begin();

			result = em.createQuery(query).getResultList();

			if (em.getTransaction().isActive())
				em.getTransaction().commit();

		} catch (Exception e) {
			if (em.getTransaction().isActive())
				em.getTransaction().rollback();
			throw new RuntimeException(e);
		}

		return result;
	}
	
	@SuppressWarnings("unchecked")
	public static List<Object> executaQuerySqlNativo(String query) {

		List<Object> result = null;

		try {

			if (!em.getTransaction().isActive())
				em.getTransaction().begin();

			result = ((Session) em.getDelegate()).createSQLQuery(query).list();

			if (em.getTransaction().isActive())
				em.getTransaction().commit();

		} catch (Exception e) {
			if (em.getTransaction().isActive())
				em.getTransaction().rollback();
			throw new RuntimeException(e);
		}

		return result;
	}

	public static Object findById(Long id, Class<?> clazz){
		/*try{
			if (!em.getTransaction().isActive())
				em.getTransaction().begin();

			Object obj = em.find(clazz, id);

			if (em.getTransaction().isActive())
				em.getTransaction().commit();
			return obj;
		} catch (Exception e) {
			if (em.getTransaction().isActive())
				em.getTransaction().rollback();
			throw new RuntimeException(e);
		}*/
		
		return em.find(clazz, id);
	}

	@SuppressWarnings("unchecked")
	public static List<Object> lista(Class<?> clazz){

		try {
			if (!em.getTransaction().isActive())
				em.getTransaction().begin();

			Session session = (Session) em.getDelegate();
			List<Object> lista = session.createCriteria(clazz).list();

			if (em.getTransaction().isActive())
				em.getTransaction().commit();

			return lista;

		} catch (Exception e) {
			if (em.getTransaction().isActive())
				em.getTransaction().rollback();
			throw new RuntimeException(e);
		}
	}

	public static void excluir(Long id, Class<?> clazz) throws RollbackException{
		try {
			if (!em.getTransaction().isActive())
				em.getTransaction().begin();

			em.remove(findById(id, clazz));

			if (em.getTransaction().isActive())
				em.getTransaction().commit();

		} catch (HibernateException e) {
			if (em.getTransaction().isActive())
				em.getTransaction().rollback();
			throw new RuntimeException(e);
		}
	}

	public static void excluir (Object obj){
		try {
			if (!em.getTransaction().isActive())
				em.getTransaction().begin();

			em.remove(obj);

			if (em.getTransaction().isActive())
				em.getTransaction().commit();

		} catch (Exception e) {
			if (em.getTransaction().isActive())
				em.getTransaction().rollback();
			throw new RuntimeException(e);
		}
	}

	@SuppressWarnings("unchecked")
	public static List<Object> listaCriterio(Class<?> clazz, List<ConsultGeneric> criterios) {

		if (!em.getTransaction().isActive())
			em.getTransaction().begin();

		try {

			List<Object> lista = null;
			Session session = (Session) em.getDelegate();

			if (criterios.size() < 1) 
				return null;

			Criteria crit = session.createCriteria(clazz);

			for ( ConsultGeneric cg : criterios ) {
				if ( cg.getTipoConsulta().equals(TipoConsultaOrdenacao.EQUAL) ){
					crit.add(Restrictions.eq(cg.getNomeCampo(), cg.getValor()));
				} else if ( cg.getTipoConsulta().equals(TipoConsultaOrdenacao.LIKE) ) {
					crit.add(Restrictions.ilike(cg.getNomeCampo(), "%" + cg.getValor() + "%"));
				} else if ( cg.getTipoConsulta().equals(TipoConsultaOrdenacao.IN) ) {
					crit.add(Restrictions.in(cg.getNomeCampo(), (Object[]) cg.getValor()));
				}
			}

			for ( ConsultGeneric cg : criterios ) {
				if ( cg.getTipoConsulta().equals(TipoConsultaOrdenacao.ASC) ) {
					crit.addOrder(Order.asc(cg.getNomeCampo()));
				} else if ( cg.getTipoConsulta().equals(TipoConsultaOrdenacao.DESC) ) {
					crit.addOrder(Order.desc(cg.getNomeCampo()));
				}
			}

			lista = crit.list();

			if (em.getTransaction().isActive())
				em.getTransaction().commit();

			return lista;
		} catch (Exception e) {
			if (em.getTransaction().isActive())
				em.getTransaction().rollback();
			throw new RuntimeException(e);
		}
	}

	public static EntityManager getEntityManager() {
		return em;
	}
}
